Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


meshchatx/src/backend/database/sticker_packs.py 22b4fcce096023ec706bab5449805e34a2912643 (22b4fcce) Text, 7.65 KB

T8b949e# SPDX-License-Identifier: 0BSD

T8b949e"""Data access object for sticker packs.

Packs group multiple stickers under a single user-facing label so they can be
exported, shared with peers over LXMF, or installed from a peer's pack
attachment. Stickers belonging to a pack reference it via
user_stickers.pack_id.
"""

Tff7b72from T7ee787__future__ Tff7b72import Te6edf3annotations

Tff7b72import T7ee787sqlite3
Tff7b72import T7ee787time

Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backend Tff7b72import Te6edf3sticker_pack_utilsTb4b4b4, Te6edf3sticker_utils

Te6edf3_PACK_COLUMNS Tff7b72= Tb4b4b4(
Ta5d6ff"Ta5d6ffid, identity_hash, title, short_name, description, pack_type, author, Ta5d6ff"
Ta5d6ff"Ta5d6ffis_strict, cover_sticker_id, sort_order, created_at, updated_atTa5d6ff"
Tb4b4b4)


Tff7b72class T56d364UserStickerPacksDAOTb4b4b4:
T8b949e"""CRUD for user_sticker_packs."""

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3providerTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffprovider Tff7b72= Te6edf3provider

Tff7b72def Td2a8ffcount_for_identityTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657intTb4b4b4:
T8b949e"""Return the number of packs stored for identity_hash."""
Te6edf3row Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchoneTb4b4b4(
Ta5d6ff"Ta5d6ffSELECT COUNT(*) AS c FROM user_sticker_packs WHERE identity_hash = ?Ta5d6ff"Tb4b4b4,
Tb4b4b4(Te6edf3identity_hashTb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return Tffa657intTb4b4b4(Te6edf3rowTb4b4b4[Ta5d6ff"Ta5d6ffcTa5d6ff"Tb4b4b4]Tb4b4b4) Tff7b72if Te6edf3row Tff7b72else T79c0ff0

Tff7b72def Td2a8fflist_for_identityTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4)Tb4b4b4:
T8b949e"""List packs for identity_hash ordered by user-defined sort order."""
Tff7b72return Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchallTb4b4b4(
Ta5d6fffTa5d6ff"""
Ta5d6ff SELECT Tffd700{Te6edf3_PACK_COLUMNSTffd700}
Ta5d6ff FROM user_sticker_packs
Ta5d6ff WHERE identity_hash = ?
Ta5d6ff ORDER BY sort_order ASC, id ASC
Ta5d6ff Ta5d6ff"""Tb4b4b4,
Tb4b4b4(Te6edf3identity_hashTb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8ffget_rowTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3pack_idTb4b4b4: Tffa657intTb4b4b4, Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4)Tb4b4b4:
T8b949e"""Fetch a single pack row scoped to identity_hash."""
Tff7b72return Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchoneTb4b4b4(
Ta5d6fffTa5d6ff"""
Ta5d6ff SELECT Tffd700{Te6edf3_PACK_COLUMNSTffd700}
Ta5d6ff FROM user_sticker_packs
Ta5d6ff WHERE id = ? AND identity_hash = ?
Ta5d6ff Ta5d6ff"""Tb4b4b4,
Tb4b4b4(Te6edf3pack_idTb4b4b4, Te6edf3identity_hashTb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8ffget_by_short_nameTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4, Te6edf3short_nameTb4b4b4: Tffa657strTb4b4b4)Tb4b4b4:
T8b949e"""Fetch a pack by its identity-scoped short_name slug."""
Tff7b72return Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchoneTb4b4b4(
Ta5d6fffTa5d6ff"""
Ta5d6ff SELECT Tffd700{Te6edf3_PACK_COLUMNSTffd700}
Ta5d6ff FROM user_sticker_packs
Ta5d6ff WHERE identity_hash = ? AND short_name = ?
Ta5d6ff Ta5d6ff"""Tb4b4b4,
Tb4b4b4(Te6edf3identity_hashTb4b4b4, Te6edf3short_nameTb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8ffinsertTb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4,
Te6edf3titleTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4,
Tff7b72*Tb4b4b4,
Te6edf3short_nameTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3descriptionTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3pack_typeTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3authorTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3is_strictTb4b4b4: Tffa657bool Tff7b72= Tff7b72TrueTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4:
T8b949e"""Create a new pack. Raises ValueError on quota or short_name clash."""
Tff7b72if Tb4b4b4(
Tff7b72selfTff7b72.Td2a8ffcount_for_identityTb4b4b4(Te6edf3identity_hashTb4b4b4)
Tff7b72>Tff7b72= Te6edf3sticker_utilsTff7b72.Td2a8ffMAX_STICKER_PACKS_PER_IDENTITY
Tb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffpack_limit_reachedTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3sn Tff7b72= Te6edf3sticker_pack_utilsTff7b72.Td2a8ffsanitize_pack_short_nameTb4b4b4(Te6edf3short_nameTb4b4b4)
Tff7b72if Te6edf3sn Tff7b72is Tff7b72not Tff7b72None Tff7b72and Tff7b72selfTff7b72.Td2a8ffget_by_short_nameTb4b4b4(Te6edf3identity_hashTb4b4b4, Te6edf3snTb4b4b4) Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffduplicate_pack_short_nameTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3now Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3cur Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(
T8b949e"""
INSERT INTO user_sticker_packs (
identity_hash, title, short_name, description, pack_type,
author, is_strict, cover_sticker_id, sort_order,
created_at, updated_at
)
VALUES (?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?)
"""Tb4b4b4,
Tb4b4b4(
Te6edf3identity_hashTb4b4b4,
Te6edf3sticker_pack_utilsTff7b72.Td2a8ffsanitize_pack_titleTb4b4b4(Te6edf3titleTb4b4b4)Tb4b4b4,
Te6edf3snTb4b4b4,
Te6edf3sticker_pack_utilsTff7b72.Td2a8ffsanitize_pack_descriptionTb4b4b4(Te6edf3descriptionTb4b4b4)Tb4b4b4,
Te6edf3sticker_pack_utilsTff7b72.Td2a8ffsanitize_pack_typeTb4b4b4(Te6edf3pack_typeTb4b4b4)Tb4b4b4,
Tb4b4b4(Te6edf3author Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4[Tb4b4b4:T79c0ff80Tb4b4b4] Tff7b72or Tff7b72NoneTb4b4b4,
T79c0ff1 Tff7b72if Te6edf3is_strict Tff7b72else T79c0ff0Tb4b4b4,
Tff7b72selfTff7b72.Td2a8ffcount_for_identityTb4b4b4(Te6edf3identity_hashTb4b4b4)Tb4b4b4,
Te6edf3nowTb4b4b4,
Te6edf3nowTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72except Te6edf3sqlite3Tff7b72.Td2a8ffIntegrityError Tff7b72as Te6edf3excTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffduplicate_pack_short_nameTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4) Tff7b72from T7ee787exc
Tff7b72return Tffa657dictTb4b4b4(Tff7b72selfTff7b72.Td2a8ffget_rowTb4b4b4(Te6edf3curTff7b72.Td2a8fflastrowidTb4b4b4, Te6edf3identity_hashTb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffupdateTb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3pack_idTb4b4b4: Tffa657intTb4b4b4,
Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4,
Tff7b72*Tb4b4b4,
Te6edf3titleTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3descriptionTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3pack_typeTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3cover_sticker_idTb4b4b4: Tffa657int Tff7b72| Tff7b72None Tff7b72| Tffa657object Tff7b72= Tff7b72.Tff7b72.Tff7b72.Tb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
T8b949e"""Update mutable fields of an existing pack.

cover_sticker_id uses a sentinel default so callers can clear the
cover by passing None while leaving it untouched when omitted.
"""
Te6edf3existing Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_rowTb4b4b4(Te6edf3pack_idTb4b4b4, Te6edf3identity_hashTb4b4b4)
Tff7b72if Tff7b72not Te6edf3existingTb4b4b4:
Tff7b72return Tff7b72False
Te6edf3new_title Tff7b72= Tb4b4b4(
Te6edf3sticker_pack_utilsTff7b72.Td2a8ffsanitize_pack_titleTb4b4b4(Te6edf3titleTb4b4b4)
Tff7b72if Te6edf3title Tff7b72is Tff7b72not Tff7b72None
Tff7b72else Te6edf3existingTb4b4b4[Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4]
Tb4b4b4)
Te6edf3new_desc Tff7b72= Tb4b4b4(
Te6edf3sticker_pack_utilsTff7b72.Td2a8ffsanitize_pack_descriptionTb4b4b4(Te6edf3descriptionTb4b4b4)
Tff7b72if Te6edf3description Tff7b72is Tff7b72not Tff7b72None
Tff7b72else Te6edf3existingTb4b4b4[Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4]
Tb4b4b4)
Te6edf3new_type Tff7b72= Tb4b4b4(
Te6edf3sticker_pack_utilsTff7b72.Td2a8ffsanitize_pack_typeTb4b4b4(Te6edf3pack_typeTb4b4b4)
Tff7b72if Te6edf3pack_type Tff7b72is Tff7b72not Tff7b72None
Tff7b72else Te6edf3existingTb4b4b4[Ta5d6ff"Ta5d6ffpack_typeTa5d6ff"Tb4b4b4]
Tb4b4b4)
Te6edf3new_cover Tff7b72= Tb4b4b4(
Te6edf3existingTb4b4b4[Ta5d6ff"Ta5d6ffcover_sticker_idTa5d6ff"Tb4b4b4]
Tff7b72if Te6edf3cover_sticker_id Tff7b72is Tff7b72.Tff7b72.Tff7b72.
Tff7b72else Te6edf3cover_sticker_id
Tb4b4b4)
Te6edf3cur Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(
T8b949e"""
UPDATE user_sticker_packs
SET title = ?, description = ?, pack_type = ?, cover_sticker_id = ?,
updated_at = ?
WHERE id = ? AND identity_hash = ?
"""Tb4b4b4,
Tb4b4b4(
Te6edf3new_titleTb4b4b4,
Te6edf3new_descTb4b4b4,
Te6edf3new_typeTb4b4b4,
Te6edf3new_coverTb4b4b4,
Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3pack_idTb4b4b4,
Te6edf3identity_hashTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3curTff7b72.Td2a8ffrowcount Tff7b72> T79c0ff0

Tff7b72def Td2a8ffreorderTb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4,
Te6edf3ordered_pack_idsTb4b4b4: Tffa657listTb4b4b4[Tffa657intTb4b4b4]Tb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657intTb4b4b4:
T8b949e"""Persist a new sort order for the listed packs."""
Te6edf3now Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Te6edf3updated Tff7b72= T79c0ff0
Tff7b72for Te6edf3indexTb4b4b4, Te6edf3pid Tff7b72in Tffa657enumerateTb4b4b4(Te6edf3ordered_pack_idsTb4b4b4)Tb4b4b4:
Te6edf3cur Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(
T8b949e"""
UPDATE user_sticker_packs
SET sort_order = ?, updated_at = ?
WHERE id = ? AND identity_hash = ?
"""Tb4b4b4,
Tb4b4b4(Te6edf3indexTb4b4b4, Te6edf3nowTb4b4b4, Tffa657intTb4b4b4(Te6edf3pidTb4b4b4)Tb4b4b4, Te6edf3identity_hashTb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3updated Tff7b72+Tff7b72= Te6edf3curTff7b72.Td2a8ffrowcount
Tff7b72return Te6edf3updated

Tff7b72def Td2a8ffdeleteTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3pack_idTb4b4b4: Tffa657intTb4b4b4, Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
T8b949e"""Delete a pack and detach its stickers (set pack_id to NULL)."""
Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(
T8b949e"""
UPDATE user_stickers SET pack_id = NULL
WHERE pack_id = ? AND identity_hash = ?
"""Tb4b4b4,
Tb4b4b4(Te6edf3pack_idTb4b4b4, Te6edf3identity_hashTb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3cur Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(
Ta5d6ff"Ta5d6ffDELETE FROM user_sticker_packs WHERE id = ? AND identity_hash = ?Ta5d6ff"Tb4b4b4,
Tb4b4b4(Te6edf3pack_idTb4b4b4, Te6edf3identity_hashTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3curTff7b72.Td2a8ffrowcount Tff7b72> T79c0ff0

Tff7b72def Td2a8ffdelete_with_stickersTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3pack_idTb4b4b4: Tffa657intTb4b4b4, Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
T8b949e"""Delete a pack and all of its stickers."""
Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(
Ta5d6ff"Ta5d6ffDELETE FROM user_stickers WHERE pack_id = ? AND identity_hash = ?Ta5d6ff"Tb4b4b4,
Tb4b4b4(Te6edf3pack_idTb4b4b4, Te6edf3identity_hashTb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3cur Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(
Ta5d6ff"Ta5d6ffDELETE FROM user_sticker_packs WHERE id = ? AND identity_hash = ?Ta5d6ff"Tb4b4b4,
Tb4b4b4(Te6edf3pack_idTb4b4b4, Te6edf3identity_hashTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3curTff7b72.Td2a8ffrowcount Tff7b72> T79c0ff0


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────